package cn.cdeden.job.snailjob.snailjob.service;

import cn.cdeden.job.snailjob.snailjob.domain.enums.AdRegionConstant;
import cn.cdeden.system.api.RemoteDeptService;
import cn.cdeden.system.api.RemoteUserService;
import cn.cdeden.system.api.domain.vo.RemoteDeptVo;
import cn.cdeden.system.api.domain.vo.RemoteUserVo;
import lombok.RequiredArgsConstructor;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Component;

import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.LdapContext;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@Component
@RequiredArgsConstructor
public class SyncUserService {

    @DubboReference
    private RemoteUserService userService;

    @DubboReference
    private RemoteDeptService deptService;

    private final LdapSevice ldapSevice;

    private static final String AD_DOMAIN_DOMAINNAME = "ad_domain_domainName";
    private static final String AD_DOMAIN_OU = "ad_domain_ou";


    public void syncUser(LdapContext ctx, RemoteUserVo user, Long deptId) {
        // 查找用户是否已存在于系统中
        RemoteUserVo existingUser = userService.selectUserByUserName(user.getUserName());
        RemoteDeptVo byId = deptService.getById(deptId);

        if (existingUser == null) {

            // 如果用户不存在，则创建新用户并保存
            RemoteUserVo newUser = new RemoteUserVo();
            newUser.setUserName(user.getUserName());
            newUser.setNickName(user.getNickName());
            newUser.setEmail(user.getEmail());
            newUser.setPhonenumber(user.getPhonenumber());
            newUser.setSex(user.getSex());
            newUser.setDeptId(deptId);
            if (byId.getPath() != null && byId.getPath().contains("离职")) {
                newUser.setStatus("1");
            } else {
                newUser.setStatus("0");
            }

            // 保存新用户
            userService.save(newUser, null); // 第二个参数可能是用户密码，可以根据具体情况传递

            // 关联用户角色（示例中默认关联角色ID为2的角色）
            userService.saveUserRole(newUser.getUserId(),5L);

        } else {
            // 用户有信息更新，则更新用户信息
            Boolean aBoolean = checkQuality(existingUser, user, deptId);

            if(!(aBoolean)){
                existingUser.setNickName(user.getNickName());
                existingUser.setEmail(user.getEmail());
                existingUser.setPhonenumber(user.getPhonenumber());
                existingUser.setSex(user.getSex());
                existingUser.setDeptId(deptId);
//                existingUser.setJobNumber(deptService.getById(deptId).getPath());
                if (byId.getPath() != null && byId.getPath().contains("离职")) {
                    existingUser.setSex("1");
                } else {
                    existingUser.setSex("0");
                }

                // 更新用户信息
                userService.updateById(existingUser);
            }
        }
    }

    private Boolean checkQuality(RemoteUserVo existingUser,RemoteUserVo newUser,Long deptId){
        return Objects.equals(existingUser.getNickName(), newUser.getNickName())
            && Objects.equals(existingUser.getEmail(), newUser.getEmail())
            && Objects.equals(existingUser.getPhonenumber(), newUser.getPhonenumber())
            && Objects.equals(existingUser.getSex(), newUser.getSex())
            && Objects.equals(existingUser.getDeptId(), deptId);
    }

    List<RemoteUserVo> getAdUsers(LdapContext ctx, Map<String, String> config, String path) throws NamingException {
        List<RemoteUserVo> userList = new ArrayList<>();

        //AD域节点结构
        String domainName = config.get(AD_DOMAIN_DOMAINNAME);
        String[] split = domainName.split("\\.");
        String dc = "";
        for (int i = 0; i < split.length; i++) {
            dc = dc + ",DC=" + split[i];
        }

        // 构建searchBase
        String searchBase;
        if (path != null && !path.isEmpty()) {
            String[] parts = path.split("/");
            StringBuilder ouBuilder = new StringBuilder();
            for (int i = parts.length - 1; i >= 0; i--) {
                if (i == 0) {
                    continue;
                }
                ouBuilder.append("OU=").append(parts[i]);
                if (i != 0 && i != 1) {
                    ouBuilder.append(",");
                }
            }
            searchBase = ouBuilder + dc;
        } else {
            searchBase = "OU=" + config.get(AD_DOMAIN_OU) + dc;
        }

        NamingEnumeration<SearchResult> answer = getUserSearchResult(ctx, AdRegionConstant.AD_USER_FILTER, searchBase);
        while (answer.hasMoreElements()) {
            SearchResult sr = answer.next();
            RemoteUserVo userDto = new RemoteUserVo();
            userDto.setUserName(ldapSevice.getAttrValue(sr, "sAMAccountName"));
            userDto.setNickName(ldapSevice.getAttrValue(sr, "name"));
            userDto.setPhonenumber(ldapSevice.getAttrValue(sr, "telephoneNumber"));

            String name = ldapSevice.getAttrValue(sr, "name");
            String canonicalName = ldapSevice.getAttrValue(sr, "canonicalName");
            String deptPath = canonicalName.substring(0, canonicalName.lastIndexOf("/" + name));
            List<RemoteDeptVo> byPath = deptService.getByPath(deptPath);
            if (byPath != null && byPath.size() > 0) {
                userDto.setDeptId(byPath.get(0).getDeptId());
            }

            String email = ldapSevice.getAttrValue(sr, "sAMAccountName") + "@user.com";
            if (ldapSevice.getAttrValue(sr, "mail") != null) {
                email = ldapSevice.getAttrValue(sr, "mail");
            }
            userDto.setEmail(email);
            userDto.setSex("0");
            userDto.setStatus("0");

            userList.add(userDto);
        }
        return userList;
    }

    public NamingEnumeration<SearchResult> getUserSearchResult(LdapContext ctx, String searchFilter, String searchBase) throws
        NamingException {
        //搜索控制器
        SearchControls searchCtls = new SearchControls();
        //创建搜索控制器
        searchCtls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
        String returnedAtts[] = {"canonicalName", "distinguishedName", "objectGUID",
            "name", "userPrincipalName", "departmentNumber", "telephoneNumber", "homePhone",
            "mobile", "department", "sAMAccountName", "whenChanged", "primaryGroupID", "mail"}; // 定制返回属性
        searchCtls.setReturningAttributes(returnedAtts);
        NamingEnumeration<SearchResult> answer = ctx.search(searchBase, searchFilter, searchCtls);
        return answer;
    }

}
